#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
"""
    Copyright by HongyeDBA
"""
# Docker is required.


import os
import sys
import time
import getopt


DEBUG_MODE = False


# ------------------------------------------------------------------------------
# FUNCTION: Execute OS Command
# ------------------------------------------------------------------------------
def exec_command(command: str, result_type: str = 'str') -> str:
    if DEBUG_MODE:
        print('[COMMAND]: {}'.format(command))
    cmd_result = os.popen('{} 2>&1'.format(command)).read().strip()
    if result_type != 'str':
        cmd_result = [x.strip() for x in cmd_result.split('\n')]
    if DEBUG_MODE:
        print('[RESULT]: [{}]'.format(cmd_result))
    return cmd_result


# ------------------------------------------------------------------------------
# Parse options
# ------------------------------------------------------------------------------
my_opt, _ = getopt.getopt(sys.argv[1:], 'hc:d:f:', ['help', 'debug', 'connection=', 'db-list=', 'file='])
option_lists = dict(my_opt)


if '-h' in option_lists or '--help' in option_lists or ('-f' not in option_lists and '--file' not in option_lists):
    print('')
    print('Batch executor can used to run compat-tools in multiple databases')
    print('')
    print('Usage:')
    print('    python3 batch_executor.py [options] -f <script-file>')
    print('')
    print('Options:')
    print('    -h/--help       : Show help message')
    print('       --debug      : Show command executed and command output for debug')
    print('    -c/--connection : Database connection options used in gsql command')
    print('    -d/--db-list    : Target database to run the script, default is [all]')
    print('                    :   Format: db1,db2,...')
    print('    -f/--file       : Target scripts to be ran, default is [runMe.sql]')
    print('                    :   Valid: runMe.sql, checkMe.sql')
    print('')
    sys.exit(0)

connection_options = option_lists['-c'] if '-c' in option_lists else option_lists['--connection'] if '--connection' in option_lists else ''
db_list = option_lists['-d'] if '-d' in option_lists else option_lists['--db-list'] if '--db-list' in option_lists else ''
script_file = option_lists['-f'] if '-f' in option_lists else option_lists['--file']
DEBUG_MODE = True if '--debug' in option_lists else False

if not exec_command('which gsql'):
    print('[ERROR]: Command [gsql] does not found !')
    print('         OS env PATH [{}]'.format(os.environ['PATH']))
    sys.exit(1)

if script_file not in ('runMe.sql', 'checkMe.sql'):
    print('[ERROR]: Script file can choose one of [runMe.sql, checkMe.sql] !')
    sys.exit(1)
elif not os.path.exists(script_file):
    print('[ERROR]: Script file does not exists !')
    sys.exit(1)

db_list_valid = set(exec_command("""gsql -qtc "select datname from pg_database where datname not in ('template0', 'template1')" """, 'line'))
if db_list:
    db_list = set([x.strip() for x in db_list.split(',')])
    db_list_valid = db_list_valid.intersection(db_list)

if not db_list_valid:
    print('[ERROR]: No target database found !')
    sys.exit(1)

if connection_options:
    print('[OPTION] connection_option = [{}]'.format(connection_options))
print('[OPTION] db_list = [{}]'.format(db_list_valid))
print('[OPTION] file = [{}]'.format(script_file))


# ------------------------------------------------------------------------------
# Execute script
# ------------------------------------------------------------------------------
db_result = {}
for db_name in db_list_valid:
    db_result[db_name] = []
    for res_line in exec_command('gsql {} -d {} -f {}'.format(connection_options, db_name, script_file), 'line'):
        if res_line.startswith('gsql:'):
            # gsql:runMe.sql:146: NOTICE:  -- =====================================================================
            # gsql:runMe.sql:146: NOTICE:  -- Compat Object List:
            # gsql:runMe.sql:146: NOTICE:  -- =====================================================================
            # gsql:runMe.sql:146: NOTICE:     | type      | name                                                                   | version | language        | operation            |
            # gsql:runMe.sql:146: NOTICE:     |-----------|------------------------------------------------------------------------|---------|-----------------|----------------------|
            line_elem = res_line.split(':', maxsplit=4)
            if len(line_elem) == 5:
                db_result[db_name].append(line_elem[-1])
print('')
print('-' * 79)
print('')
max_db_len = max([len(x) for x in db_result]) + 1
PRINT_TEMPLATE = '{{:{}s}}: {{}}'.format(max_db_len)
for db_name in db_result:
    for res_line in db_result[db_name]:
        print(PRINT_TEMPLATE.format(db_name, res_line.strip(' -')))
    print('')
    print('-' * 79)
    print('')
